package library.http.progress;


import java.io.IOException;

import okhttp3.MediaType;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

public class ProgressResponseBody extends ResponseBody {
    //实际的待包装响应体
    private final ResponseBody responseBody;
    //包装完成的BufferedSource
    private BufferedSource bufferedSource;
    private long contentLength = -1;

    private final ProgressPublisher publisher;


    public ProgressResponseBody(ResponseBody responseBody, final ProgressPublisher publisher) {
        this.responseBody = responseBody;
        this.publisher = publisher;
    }

    @Override
    public MediaType contentType() {
        return responseBody.contentType();
    }

    @Override
    public long contentLength() {
        long length = responseBody.contentLength();
        if (length == -1) {
            length = contentLength;
        }
        return length;
    }

    public void setContentLength(long contentLength) {
        this.contentLength = contentLength;
    }

    @Override
    public BufferedSource source() {
        if (bufferedSource == null) {
            //包装
            bufferedSource = Okio.buffer(source(responseBody.source()));
        }
        return bufferedSource;
    }

    private Source source(Source source) {
        return new ForwardingSource(source) {
            //当前读取字节数
            long range = 0L;
            long length = -1L;

            long lastRange = -1L;

            @Override
            public long read(Buffer sink, long byteCount) throws IOException {
                if (range == 0) {
                    publisher.flagStart();
                }
                long bytesRead;
                try {
                    bytesRead = super.read(sink, byteCount);
                } catch (IOException e) {
                    if (publisher != null) {
                        publisher.cancel();
                    }
                    throw e;
                }
                //增加当前读取的字节数，如果读取完成了bytesRead会返回-1
                range += bytesRead != -1 ? bytesRead : 0;
                if (length < 0)
                    length = contentLength();//如果contentLength()不知道长度，会返回-1
                if (publisher != null && length >= 0 && lastRange != range) {
                    publisher.publishProgress(lastRange = range, length);
                }
                return bytesRead;
            }
        };
    }

}